package com.wxyzz.cem.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.IService;
import com.wxyzz.cem.enums.LoginRole;
import com.wxyzz.cem.enums.ThreadLocalName;
import com.wxyzz.cem.exception.UserServiceException;
import com.wxyzz.cem.pojo.User;
import com.wxyzz.cem.mapper.UserMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wxyzz.cem.pojo.enums.UserRole;
import com.wxyzz.cem.pojo.enums.UserStatus;
import com.wxyzz.cem.util.EncryptUtil;
import com.wxyzz.cem.util.Result;
import com.wxyzz.cem.util.ThreadLocalUtil;
import com.wxyzz.cem.util.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author xc
 * @since 2024-07-04
 */
@Service
public class UserService extends ServiceImpl<UserMapper, User> implements IService<User> {

    @Autowired
    private UserMapper userMapper;
    
    private String generateToken(User user) {
        return TokenUtil.generate(user, LoginRole.USER, user.getPassword());
    }
    
    public String encryptPassword(User user) {
        return EncryptUtil.encryptWithSha256(user.getPassword(), user.getAccount());
    }
    
    public String login(User userLoginInfo) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccount, userLoginInfo.getAccount());
        User user = this.getOne(queryWrapper);
        
        if (user == null) {
            throw new UserServiceException("账号不存在！");
        }
        
        String encryptPassword = EncryptUtil.encryptWithSha256(userLoginInfo.getPassword(), userLoginInfo.getAccount());
        if (!encryptPassword.equals(user.getPassword())) {
            throw new UserServiceException("密码错误！");
        }
        
        if (user.getStatus() == UserStatus.DISABLE) {
            throw new UserServiceException("该账号已被禁封！");
        }
        
        return generateToken(user);
    }
    
    public void register(User user) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getAccount, user.getAccount());
        User exitUser = this.getOne(queryWrapper);
        if (exitUser != null) {
            throw new UserServiceException("该账号已存在！");
        }
        
        String encryptPassword = EncryptUtil.encryptWithSha256(user.getPassword(), user.getAccount());
        user.setPassword(encryptPassword);
        boolean success = this.save(user);
        
        if (!success) {
            throw new UserServiceException("系统错误，注册失败！");
        }
    }
    
    public String updateUser(User user) {
        // 禁止用户修改自己的状态
        user.setStatus(null);
        // 禁止用户修改自己的角色
        user.setRole(null);
        // 禁止用户修改自己的班级
        user.setClassId(null);
        boolean success = this.updateById(user);
        if (!success) {
            throw new UserServiceException("系统错误，修改失败！");
        }
        
        user = this.getById(user.getId());
        return generateToken(user);
    }

    public void disableUser(Integer id) {
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在,不能进行禁封操作");
        }
        user.setStatus(UserStatus.DISABLE);
        userMapper.updateById(user);

    }

    public void enableUser(Integer id) {
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new RuntimeException("用户不存在，不能进行解封操作");
        }
        user.setStatus(UserStatus.ENABLE);
        userMapper.updateById(user);
    }

    public PageDTO<User> PageList(Integer page, Integer size, String name, String account, String phone) {
        Page<User> userPage = new Page<>(page,size);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(Objects.nonNull(name),"name",name);
        queryWrapper.like(Objects.nonNull(account),"account",account);
        queryWrapper.like(Objects.nonNull(phone),"phone",phone);
        Page<User> selectPage = userMapper.selectPage(userPage, queryWrapper);
        PageDTO<User> userPageDTO = new PageDTO<>();
        BeanUtil.copyProperties(selectPage,userPageDTO);
        return userPageDTO;
    }

    public User getCurrentUser() {
        Integer userId = ThreadLocalUtil.get(ThreadLocalName.USER.getValue(), User.class).getId();
        return userMapper.selectById(userId);
    }
    
    public String refreshTokenById(Integer id) {
        User user = this.getById(id);
        return generateToken(user);
    }
    
    public Page<User> getClassMemberById(Integer classId, Integer page, Integer size, String name, String account, String phone) {
        Page<User> userPage = new Page<>(page, size);
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getClassId, classId);
        queryWrapper.like(StrUtil.isNotBlank(name), User::getName, name);
        queryWrapper.like(StrUtil.isNotBlank(account), User::getAccount, account);
        queryWrapper.like(StrUtil.isNotBlank(phone), User::getPhone, phone);
        return this.page(userPage, queryWrapper);
    }
    
    public void setClassAdmin(Integer userId, Integer classId) {
        User user = this.getById(userId);
        if (!Objects.equals(user.getClassId(), classId)) {
            throw new UserServiceException("该用户不属于该班级");
        }
        
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(User::getRole, UserRole.USER);
        updateWrapper.eq(User::getClassId, classId);
        this.update(updateWrapper);
        
        user.setRole(UserRole.CLASS_ADMIN);
        this.updateById(user);
    }
}
